<?php
/**
 * Created by PhpStorm.
 * User: yiyu
 * Email: smalleasyu@gmail.com
 * Date: 2020-01-30 22:46:14
 * Desc:
 */

namespace app\base\service\Pay;

use app\base\service\BaseService;
use app\base\service\WeChat\WeChatBaseService;
use app\base\model\order\Order;
use EasyWeChat\Factory;
use function EasyWeChat\Kernel\Support\generate_sign;
use app\core\exception\{BusinessException, ErrorCode};
use app\core\log\Log4dd;

class WxPayService extends BaseService
{

    public static function miniProgramCreateWxOrder($app_id, $order_info)
    {

        //微信统一下单接口 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

        $config = WeChatBaseService::instance()->getConfigByAppId($app_id);

        if (!isset($config['app_id'], $config['mch_id'], $config['key']) || empty($config['app_id']) || empty($config['secret']) || empty($config['key'])) {
            Log4dd::error('小程序微信下单失败,app_id配置错误', ['app_id' => $app_id, $config]);
            throw new BusinessException(ErrorCode::MINI_PROGRAM_LACK_PARAMS, '小程序参数配置错误');
        }

        $new_config = [
            'app_id' => $config['app_id'],
            'mch_id' => $config['mch_id'],
            'key' => $config['key'],
            'cert_path' => $config['cert_path'],
            'key_path' => $config['key_path'],
            'notify_url' => $config['notify_url'],
        ];

        $app = Factory::payment($new_config);

        if (empty($order_info['total_fee'])) {
            Log4dd::error('小程序微信下单失败,支付金额错误', ['order_info' => $order_info]);
            throw new BusinessException(ErrorCode::DATA_OPERATE_FAIL, '支付金额错误');
        }



        $order_data = [
            'body' => $order_info['body'] ?? '',
            'out_trade_no' => $order_info['out_trade_no'] ?? '',
            'total_fee' => $order_info['total_fee'] * 100,//todo 这里需要乘以100，因为微信已分来计算下单金额
            //'total_fee' => 1,
            'spbill_create_ip' => $order_info['spbill_create_ip'] ?? '',
            'trade_type' => 'JSAPI',
            'openid' => $order_info['open_id'] ?? '',
        ];

        Log4dd::info('微信统一下单请求数据', ['app_id' => $app_id, 'order_data' => $order_data]);

        try {
            $result = $app->order->unify($order_data);
        } catch (BusinessException $e) {
            Log4dd::error("请求微信统一下单接口失败:{$e->getMessage()}", func_get_args(), $e);
            throw new BusinessException(ErrorCode::COMMON_ERROR, '下单失败');
        }

        // $result:
//{
//    "return_code": "SUCCESS",
//    "return_msg": "OK",
//    "appid": "wx2421b1c4390ec4sb",
//    "mch_id": "10000100",
//    "nonce_str": "IITRi8Iabbblz1J",
//    "openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeSs6o",
//    "sign": "7921E432F65EB8ED0CE9755F0E86D72F2",
//    "result_code": "SUCCESS",
//    "prepay_id": "wx201411102639507cbf6ffd8b0779950874",
//    "trade_type": "JSAPI"
//}

        $log = ['app_id' => $app_id, 'order_info' => $order_info, 'order_data' => $order_data, 'result' => $result];

        Log4dd::info('微信下单返回数据', $log);


        if (empty($result)) {
            throw new BusinessException(ErrorCode::COMMON_ERROR, '下单失败，微信未返回信息');
        }

        if ($result['return_code'] != 'SUCCESS') {
            throw new BusinessException(ErrorCode::COMMON_ERROR, $result['return_msg']);
        }

        if ($result['result_code'] != 'SUCCESS') {

            throw new BusinessException(ErrorCode::COMMON_ERROR, $result['err_code_des']);
        }

        unset($result['return_code'], $result['result_code'], $result['err_code'], $result['err_code_des']);

        $params = [
            'appId'     => $result['appid'], // 小程序的AppId
            'timeStamp' => time(),
            'nonceStr'  => $result['nonce_str'], // 统一下单返回的随机字符串
            'package'   => 'prepay_id=' . $result['prepay_id'], // 统一下单Id
            'signType'  => 'MD5', // 签名方法
        ];
        // 注意这里用的是商户平台的Key进行二次签名
        $params['paySign'] = generate_sign($params, $config['key']);

        return $params;
    }

    public static function checkOrderNotify($app_id)
    {
        $config = WeChatBaseService::instance()->getConfigByAppId($app_id);

        if (!isset($config['app_id'], $config['mch_id'], $config['key']) || empty($config['app_id']) || empty($config['secret']) || empty($config['key'])) {
            Log4dd::error('处理微信支付成功回调数据失败,app_id配置错误', ['app_id' => $app_id, $config]);
            throw new BusinessException(ErrorCode::MINI_PROGRAM_LACK_PARAMS, '小程序参数配置错误');
        }

        $new_config = [
            'app_id' => $config['app_id'],
            'mch_id' => $config['mch_id'],
            'key' => $config['key'],
            'cert_path' => $config['cert_path'],
            'key_path' => $config['key_path'],
            'notify_url' => $config['notify_url'],
        ];

        $app = Factory::payment($new_config);

        $response = $app->handlePaidNotify(function ($message, $fail) {
            Log4dd::info('微信支付成功回调，原始数据', $message);
            // 使用通知里的 "微信支付订单号" 或者 "商户订单号" 去自己的数据库找到订单

            $order = Order::where('order_no', $message['out_trade_no'])->find();
            Log4dd::info('微信支付成功回调，数据库数据', $order);
            if (!$order || $order['order_state'] == Order::ORDER_SUCCESS) { // 如果订单不存在 或者 订单已经支付过了
                return true; // 告诉微信，我已经处理完了，订单没找到，别再通知我了
            }

            ///////////// <- 建议在这里调用微信的【订单查询】接口查一下该笔订单的情况，确认是已经支付 /////////////
            ///
            /// 根据商户订单号查询
            //$app->order->queryByOutTradeNumber("商户系统内部的订单号（out_trade_no）");
            //根据微信订单号查询
            //$app->order->queryByTransactionId("微信订单号（transaction_id）");
            $notify_data = [];


            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    $notify_data['transaction_id'] = $message['transaction_id'];
                    $notify_data['order_state'] = Order::ORDER_SUCCESS;
                    $notify_data['pay_finish_time'] = date('Y-m-d H:i:s');
                    $notify_data['update_time'] = date('Y-m-d H:i:s');

                    Log4dd::info("微信支付成功回调，保存订单状态 success", [$order['order_id'], $notify_data]);
                    Order::where('order_id', $order['order_id'])->update($notify_data);// 保存订单
                    try {
                        return OrderService::orderSuccess($order['user_id'], $order['order_id'], $order['order_no']);
                    } catch (BusinessException $e) {
                        Log4dd::info("微信支付成功回调， 处理订单失败:{$e->getMessage()}", func_get_args(), $e);
                        return $fail($e->getMessage());
                    }

                    // 用户支付失败
                } elseif ($message['result_code'] === 'FAIL') {
                    $notify_data['order_state'] = Order::ORDER_NOT_PAY;
                    $notify_data['update_time'] = date('Y-m-d H:i:s');
                    Log4dd::info("微信支付成功回调，保存订单状态 fail", [$order['order_id'], $notify_data]);
                    Order::where('order_id', $order['order_id'])->update($notify_data);// 保存订单
                }

            } else {
                return $fail('通信失败，请稍后再通知我');
            }

            return true; // 返回处理完成
        });

        return $response->send(); // return $response;
    }

}